/**
 * @Author: jichang
 * @Date: 2024/10/28 15:44:29
 * @LastEditors: jichang
 * @LastEditTime: 2024/10/28 15:44:29
 * Description: 
 */
#pragma once
#include "simple_msg_queue.hpp"
#include "TemplateDispatcher.hpp"

namespace messaging 
{
    class close_queue {}; // 用于关闭队列消息

    // 引用receiver中的队列，对消息进行等待，以及对其进行调度
    class dispatcher {
    public:
        dispatcher(dispatcher&& other): 
                q(other.q), chained(other.chained) {
            other.chained = true;
        }
        explicit dispatcher(queue* q_): q(q_), chained(false) { }

        // 对一条消息进行处理，需要指定需要处理的消息类型，传入函数进行处理
        // 函数模板
        template<typename Message, typename Func>
        TemplateDispatcher<dispatcher, Message, Func>
        handle(Func&& f) {
            // 使用TemplateDispatcher处理指定类型的消息
            return TemplateDispatcher<dispatcher, Message, Func>
                (q, this, std::forward<Func>(f));
        }

        ~dispatcher() noexcept(false) {
            if (!chained) {
                wait_and_dispatch();
            }
        }
    private:
        // 该实例不能被拷贝
        dispatcher(dispatcher const&) = delete;
        dispatcher& operator=(dispatcher const&) = delete;

        // 允许TemplateDispatcher实例访问内部成员
        template<typename Dispatcher, typename Msg, typename Func>
        friend class TemplateDispatcher;

        void wait_and_dispatch() {
            while(1) {
                auto msg = q->wait_pop();
                dispatch(msg);
            }
        }
        // 检查是否为close_queue消息，如果是则抛出异常
        // 如果不是，函数会返回false表明消息没有被处理
        bool dispatch(std::shared_ptr<message_base> const& msg) {
            if (dynamic_cast<wrapped_message<close_queue>*>(msg.get())) {
                throw close_queue();
            }
            return false;
        }

    private:
        queue* q;
        bool chained;
    };
}